﻿/*
 * 邮件系统
 * 
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Web.Mail;
using System.Net;
using System.IO;

namespace Wjtour.Common
{
    public class SmtpMail : ISmtpMail
    {
        // Fields
        private string _body;
        private string _charset = "GB2312";
        private string _from = "";
        private string _fromName = "";
        private bool _html = false;
        private string _recipientName = "";
        private string _subject;
        private IList Attachments = new ArrayList();
        private string enter = "\r\n";
        private Hashtable ErrCodeHT = new Hashtable();
        private string errmsg;
        private bool ESmtp = false;
        private string logs = "";
        private string mailserver = "smtp.163.com";
        private int mailserverport = 25;
        private NetworkStream ns;
        private string password = "";
        private string priority = "Normal";
        private Hashtable Recipient = new Hashtable();
        private int recipientmaxnum = 5;
        private int RecipientNum = 0;
        private Hashtable RightCodeHT = new Hashtable();
        private TcpClient tc;
        private string username = "";

        // Methods
        public SmtpMail()
        {
            this.SMTPCodeAdd();
        }

        public void AddAttachment(params string[] FilePath)
        {
            if (FilePath == null)
            {
                throw new ArgumentNullException("FilePath");
            }
            for (int i = 0; i < FilePath.Length; i++)
            {
                this.Attachments.Add(FilePath[i]);
            }
        }

        public bool AddRecipient(List<string> Recipients)
        {
            if (this.Recipient == null)
            {
                this.Dispose();
                throw new ArgumentNullException("Recipients");
            }
            for (int i = 0; i < Recipients.Count; i++)
            {
                string recipients = Recipients[i].Trim();
                if (recipients == string.Empty)
                {
                    this.Dispose();
                    throw new ArgumentNullException("Recipients[" + i + "]");
                }
                if (recipients.IndexOf("@") == -1)
                {
                    this.Dispose();
                    throw new ArgumentException("Recipients.IndexOf(\"@\")==-1", "Recipients");
                }
                if (!this.AddRecipient(recipients))
                {
                    return false;
                }
            }
            return true;
        }

        private bool AddRecipient(string Recipients)
        {
            this.Recipient.Clear();
            this.RecipientNum = 0;
            if (this.RecipientNum < this.recipientmaxnum)
            {
                this.Recipient.Add(this.RecipientNum, Recipients);
                this.RecipientNum++;
                return true;
            }
            this.Dispose();
            throw new ArgumentOutOfRangeException("Recipients", "收件人过多不可多于 " + this.recipientmaxnum + " 个");
        }

        private string Base64Decode(string str)
        {
            byte[] bytes = Convert.FromBase64String(str);
            return Encoding.Default.GetString(bytes);
        }

        private string Base64Encode(string str)
        {
            return Convert.ToBase64String(Encoding.Default.GetBytes(str));
        }

        private bool Dialog(string str, string errstr)
        {
            if ((str == null) || (str.Trim() == ""))
            {
                return true;
            }
            if (this.SendCommand(str))
            {
                string str2 = this.RecvResponse();
                if (str2 != "false")
                {
                    string str3 = str2.Substring(0, 3);
                    if (this.RightCodeHT[str3] != null)
                    {
                        return true;
                    }
                    if (this.ErrCodeHT[str3] != null)
                    {
                        this.errmsg = this.errmsg + str3 + this.ErrCodeHT[str3].ToString();
                        this.errmsg = this.errmsg + this.enter;
                    }
                    else
                    {
                        this.errmsg = this.errmsg + str2;
                    }
                    this.errmsg = this.errmsg + errstr;
                }
                return false;
            }
            return false;
        }

        private bool Dialog(string[] str, string errstr)
        {
            for (int i = 0; i < str.Length; i++)
            {
                if (!this.Dialog(str[i], ""))
                {
                    this.errmsg = this.errmsg + this.enter;
                    this.errmsg = this.errmsg + errstr;
                    return false;
                }
            }
            return true;
        }

        private void Dispose()
        {
            if (this.ns != null)
            {
                this.ns.Close();
            }
            if (this.tc != null)
            {
                this.tc.Close();
            }
        }

        public string ErrCodeHTMessage(string code)
        {
            return this.ErrCodeHT[code].ToString();
        }

        private string GetStream(string FilePath)
        {
            FileStream stream = new FileStream(FilePath, FileMode.Open);
            byte[] buffer = new byte[Convert.ToInt32(stream.Length)];
            stream.Read(buffer, 0, buffer.Length);
            stream.Close();
            return Convert.ToBase64String(buffer);
        }

        private string RecvResponse()
        {
            int num;
            string str = string.Empty;
            byte[] buffer = new byte[0x400];
            try
            {
                num = this.ns.Read(buffer, 0, buffer.Length);
            }
            catch
            {
                this.errmsg = "网络连接错误";
                return "false";
            }
            if (num != 0)
            {
                str = Encoding.Default.GetString(buffer).Substring(0, num);
                this.logs = this.logs + str + this.enter;
            }
            return str;
        }

        public bool Send()
        {
            if (this.mailserver.Trim() == "")
            {
                throw new ArgumentNullException("Recipient", "必须指定SMTP服务器");
            }
            return this.SendEmail();
        }

        public bool Send(string smtpserver)
        {
            this.MailDomain = smtpserver;
            return this.Send();
        }

        public bool Send(string smtpserver, string from, string fromname, string to, string toname, bool html, string subject, string body)
        {
            this.MailDomain = smtpserver;
            this.From = from;
            this.FromName = fromname;
            this.AddRecipient(to);
            this.RecipientName = toname;
            this.Html = html;
            this.Subject = subject;
            this.Body = body;
            return this.Send();
        }

        private bool SendCommand(string str)
        {
            if ((str != null) && (str.Trim() != string.Empty))
            {
                this.logs = this.logs + str;
                byte[] bytes = Encoding.Default.GetBytes(str);
                try
                {
                    this.ns.Write(bytes, 0, bytes.Length);
                }
                catch
                {
                    this.errmsg = "网络连接错误";
                    return false;
                }
            }
            return true;
        }

        private bool SendEmail()
        {
            string[] strArray;
            string str;
            int num;
            string str3;
            try
            {
                this.tc = new TcpClient(this.mailserver, this.mailserverport);
            }
            catch (Exception exception)
            {
                this.errmsg = exception.ToString();
                return false;
            }
            this.ns = this.tc.GetStream();
            if (this.RightCodeHT[this.RecvResponse().Substring(0, 3)] == null)
            {
                this.errmsg = "网络连接失败";
                return false;
            }
            if (this.ESmtp)
            {
                strArray = new string[] { "EHLO " + this.mailserver + this.enter, "AUTH LOGIN" + this.enter, this.Base64Encode(this.username) + this.enter, this.Base64Encode(this.password) + this.enter };
                if (!this.Dialog(strArray, "SMTP服务器验证失败,请核对用户名和密码。"))
                {
                    return false;
                }
            }
            else
            {
                str = "HELO " + this.mailserver + this.enter;
                if (!this.Dialog(str, ""))
                {
                    return false;
                }
            }
            str = "MAIL FROM:<" + this.From + ">" + this.enter;
            if (!this.Dialog(str, "发件人地址错误,或不能为空"))
            {
                return false;
            }
            strArray = new string[this.recipientmaxnum];
            for (num = 0; num < this.Recipient.Count; num++)
            {
                strArray[num] = "RCPT TO:<" + this.Recipient[num].ToString() + ">" + this.enter;
            }
            if (!this.Dialog(strArray, "收件人地址有误"))
            {
                return false;
            }
            str = "DATA" + this.enter;
            if (!this.Dialog(str, ""))
            {
                return false;
            }
            object obj2 = "From:" + this.FromName + "<" + this.From + ">" + this.enter;
            str = string.Concat(new object[] { obj2, "To:=?", this.Charset.ToUpper(), "?B?", string.IsNullOrEmpty(this.RecipientName) ? "" : this.Base64Encode(this.RecipientName), "?=<", this.Recipient[0], ">", this.enter }) + "CC:";
            for (num = 1; num < this.Recipient.Count; num++)
            {
                str3 = str;
                str = str3 + this.Recipient[num].ToString() + "<" + this.Recipient[num].ToString() + ">,";
            }
            str = ((((((str + this.enter) + (((this.Subject == string.Empty) || (this.Subject == null)) ? "Subject:" : ((this.Charset == "") ? ("Subject:" + this.Subject) : ("Subject:=?" + this.Charset.ToUpper() + "?B?" + this.Base64Encode(this.Subject) + "?="))) + this.enter) + "X-Priority:" + this.priority + this.enter) + "X-MSMail-Priority:" + this.priority + this.enter) + "Importance:" + this.priority + this.enter) + "X-Mailer: Lion.Web.Mail.SmtpMail Pubclass [cn]" + this.enter) + "MIME-Version: 1.0" + this.enter;
            if (this.Attachments.Count != 0)
            {
                str3 = str + "Content-Type: multipart/mixed;" + this.enter;
                str = str3 + "\tboundary=\"=====" + (this.Html ? "001_Dragon520636771063_" : "001_Dragon303406132050_") + "=====\"" + this.enter + this.enter;
            }
            if (this.Html)
            {
                if (this.Attachments.Count == 0)
                {
                    str = ((str + "Content-Type: multipart/alternative;" + this.enter) + "\tboundary=\"=====003_Dragon520636771063_=====\"" + this.enter + this.enter) + "This is a multi-part message in MIME format." + this.enter + this.enter;
                }
                else
                {
                    str = (((str + "This is a multi-part message in MIME format." + this.enter + this.enter) + "--=====001_Dragon520636771063_=====" + this.enter) + "Content-Type: multipart/alternative;" + this.enter) + "\tboundary=\"=====003_Dragon520636771063_=====\"" + this.enter + this.enter;
                }
                str = ((((((((((str + "--=====003_Dragon520636771063_=====" + this.enter) + "Content-Type: text/plain;" + this.enter) + ((this.Charset == "") ? "\tcharset=\"iso-8859-1\"" : ("\tcharset=\"" + this.Charset.ToLower() + "\"")) + this.enter) + "Content-Transfer-Encoding: base64" + this.enter + this.enter) + this.Base64Encode("邮件内容为HTML格式,请选择HTML方式查看") + this.enter + this.enter) + "--=====003_Dragon520636771063_=====" + this.enter) + "Content-Type: text/html;" + this.enter) + ((this.Charset == "") ? "\tcharset=\"iso-8859-1\"" : ("\tcharset=\"" + this.Charset.ToLower() + "\"")) + this.enter) + "Content-Transfer-Encoding: base64" + this.enter + this.enter) + this.Base64Encode(this.Body) + this.enter + this.enter) + "--=====003_Dragon520636771063_=====--" + this.enter;
            }
            else
            {
                if (this.Attachments.Count != 0)
                {
                    str = str + "--=====001_Dragon303406132050_=====" + this.enter;
                }
                str = (((str + "Content-Type: text/plain;" + this.enter) + ((this.Charset == "") ? "\tcharset=\"iso-8859-1\"" : ("\tcharset=\"" + this.Charset.ToLower() + "\"")) + this.enter) + "Content-Transfer-Encoding: base64" + this.enter + this.enter) + this.Base64Encode(this.Body) + this.enter;
            }
            if (this.Attachments.Count != 0)
            {
                for (num = 0; num < this.Attachments.Count; num++)
                {
                    string filePath = (string)this.Attachments[num];
                    str3 = str;
                    str3 = (str3 + "--=====" + (this.Html ? "001_Dragon520636771063_" : "001_Dragon303406132050_") + "=====" + this.enter) + "Content-Type: text/plain;" + this.enter;
                    str3 = ((str3 + "\tname=\"=?" + this.Charset.ToUpper() + "?B?" + this.Base64Encode(filePath.Substring(filePath.LastIndexOf(@"\") + 1)) + "?=\"" + this.enter) + "Content-Transfer-Encoding: base64" + this.enter) + "Content-Disposition: attachment;" + this.enter;
                    str = (str3 + "\tfilename=\"=?" + this.Charset.ToUpper() + "?B?" + this.Base64Encode(filePath.Substring(filePath.LastIndexOf(@"\") + 1)) + "?=\"" + this.enter + this.enter) + this.GetStream(filePath) + this.enter + this.enter;
                }
                str3 = str;
                str = str3 + "--=====" + (this.Html ? "001_Dragon520636771063_" : "001_Dragon303406132050_") + "=====--" + this.enter + this.enter;
            }
            str = str + this.enter + "." + this.enter;
            if (!this.Dialog(str, "错误信件信息"))
            {
                return false;
            }
            str = "QUIT" + this.enter;
            if (!this.Dialog(str, "断开连接时错误"))
            {
                return false;
            }
            this.ns.Close();
            this.tc.Close();
            return true;
        }

        private void SMTPCodeAdd()
        {
            this.ErrCodeHT.Add("500", "邮箱地址错误");
            this.ErrCodeHT.Add("501", "参数格式错误");
            this.ErrCodeHT.Add("502", "命令不可实现");
            this.ErrCodeHT.Add("503", "服务器需要SMTP验证");
            this.ErrCodeHT.Add("504", "命令参数不可实现");
            this.ErrCodeHT.Add("421", "服务未就绪,关闭传输信道");
            this.ErrCodeHT.Add("450", "要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)");
            this.ErrCodeHT.Add("550", "要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)");
            this.ErrCodeHT.Add("451", "放弃要求的操作;处理过程中出错");
            this.ErrCodeHT.Add("551", "用户非本地,请尝试<forward-path>");
            this.ErrCodeHT.Add("452", "系统存储不足, 要求的操作未执行");
            this.ErrCodeHT.Add("552", "过量的存储分配, 要求的操作未执行");
            this.ErrCodeHT.Add("553", "邮箱名不可用, 要求的操作未执行(例如邮箱格式错误)");
            this.ErrCodeHT.Add("432", "需要一个密码转换");
            this.ErrCodeHT.Add("534", "认证机制过于简单");
            this.ErrCodeHT.Add("538", "当前请求的认证机制需要加密");
            this.ErrCodeHT.Add("454", "临时认证失败");
            this.ErrCodeHT.Add("530", "需要认证");
            this.RightCodeHT.Add("220", "服务就绪");
            this.RightCodeHT.Add("250", "要求的邮件操作完成");
            this.RightCodeHT.Add("251", "用户非本地, 将转发向<forward-path>");
            this.RightCodeHT.Add("354", "开始邮件输入, 以<enter>.<enter>结束");
            this.RightCodeHT.Add("221", "服务关闭传输信道");
            this.RightCodeHT.Add("334", "服务器响应验证Base64字符串");
            this.RightCodeHT.Add("235", "验证成功");
        }

        // Properties
        public string Body
        {
            get
            {
                return this._body;
            }
            set
            {
                this._body = value;
            }
        }

        public string Charset
        {
            get
            {
                return this._charset;
            }
            set
            {
                this._charset = value;
            }
        }

        public string ErrorMessage
        {
            get
            {
                return this.errmsg;
            }
        }

        public string From
        {
            get
            {
                return this._from;
            }
            set
            {
                this._from = value;
            }
        }

        public string FromName
        {
            get
            {
                return this._fromName;
            }
            set
            {
                this._fromName = value;
            }
        }

        public bool Html
        {
            get
            {
                return this._html;
            }
            set
            {
                this._html = value;
            }
        }

        public string Logs
        {
            get
            {
                return this.logs;
            }
        }

        public string MailDomain
        {
            set
            {
                string str = value.Trim();
                if (str != "")
                {
                    int index = str.IndexOf("@");
                    if (index != -1)
                    {
                        string str2 = str.Substring(0, index);
                        this.MailServerUserName = str2.Substring(0, str2.IndexOf(":"));
                        this.MailServerPassWord = str2.Substring(str2.IndexOf(":") + 1, (str2.Length - str2.IndexOf(":")) - 1);
                        str = str.Substring(index + 1, (str.Length - index) - 1);
                    }
                    index = str.IndexOf(":");
                    if (index != -1)
                    {
                        this.mailserver = str.Substring(0, index);
                        this.mailserverport = Convert.ToInt32(str.Substring(index + 1, (str.Length - index) - 1));
                    }
                    else
                    {
                        this.mailserver = str;
                    }
                }
            }
        }

        public int MailDomainPort
        {
            set
            {
                this.mailserverport = value;
            }
        }

        public string MailDomainServer
        {
            set
            {
                this.mailserver = value;
            }
        }

        public string MailServerPassWord
        {
            set
            {
                this.password = value;
            }
        }

        public string MailServerUserName
        {
            set
            {
                if (value.Trim() != "")
                {
                    this.username = value.Trim();
                    this.ESmtp = true;
                }
                else
                {
                    this.username = "";
                    this.ESmtp = false;
                }
            }
        }

        public string Priority
        {
            set
            {
                switch (value.ToLower())
                {
                    case "high":
                        this.priority = "High";
                        break;

                    case "1":
                        this.priority = "High";
                        break;

                    case "normal":
                        this.priority = "Normal";
                        break;

                    case "3":
                        this.priority = "Normal";
                        break;

                    case "low":
                        this.priority = "Low";
                        break;

                    case "5":
                        this.priority = "Low";
                        break;

                    default:
                        this.priority = "High";
                        break;
                }
            }
        }

        public int RecipientMaxNum
        {
            set
            {
                this.recipientmaxnum = value;
            }
        }

        public string RecipientName
        {
            get
            {
                return this._recipientName;
            }
            set
            {
                this._recipientName = value;
            }
        }

        public string Subject
        {
            get
            {
                return this._subject;
            }
            set
            {
                this._subject = value;
            }
        }
    }
}
